package com.wlyuan.index.domain.index.valueobj;

import com.wlyuan.index.domain.index.WaybillIndex;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import lombok.extern.slf4j.Slf4j;
import lombok.var;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.data.elasticsearch.annotations.DateFormat;
import org.springframework.data.elasticsearch.annotations.Field;
import org.springframework.data.elasticsearch.annotations.FieldType;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * @author yuanjie
 */
@Deprecated
@Data
@Slf4j
@EqualsAndHashCode(callSuper = true, exclude = {"bills", "balances"})
@ToString(callSuper = true)
public class WaybillRelation extends Relation {

    @Field(type = FieldType.Long)
    private Long billId;
    @Field(type = FieldType.Keyword)
    private String billNo;
    @Field(type = FieldType.Keyword)
    private String billName;
    @Field(type = FieldType.Integer)
    private Integer billStatus;
    @Field(type = FieldType.Date, format = DateFormat.custom, pattern = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'")
    private LocalDateTime billAt;
    @Field(type = FieldType.Boolean)
    private Boolean callBill;
    @Field(type = FieldType.Nested, index = false)
    private List<Bill> bills;
    @Field(type = FieldType.Nested, index = false)
    private Balances balances;
    @Field(type = FieldType.Keyword)
    private String customerName;

    protected Optional<Bill> bill() {
        if (CollectionUtils.isEmpty(this.bills)) {
            return Optional.empty();
        }
        return this.bills.stream().max(Comparator.comparingInt(Bill::getPriority));
    }

    synchronized
    public void addBill(Bill bill) {
        if (null == this.bills) {
            this.bills = new ArrayList<>();
        }
        var billMap = this.bills.stream().collect(Collectors.toMap(Bill::getBillId, a -> a));
        billMap.put(bill.getBillId(), bill);
        this.bills = new ArrayList<>(billMap.values());
    }

//    protected Boolean hasFee(String name, BigDecimal money) {
//        return Optional.ofNullable(this.balances).map(bas -> bas.has(name, true)).orElse(true);
//    }

    // 已加入对账单不能报价
    // 已结账不能报价
    protected boolean canQuote() {
        var payNotAllow = Optional.ofNullable(this.balances)
                .map(Balances::getOverallFee)
                .map(Balances::settled)
                .orElse(false);

        return (null == this.billId || this.canBill()) && !payNotAllow
                && Quotation.canQuote(this.getQuotationStatus());
    }

    protected boolean canBill() {
        return Bill.canBill(this.getBillStatus());
    }


    protected boolean canQuote(WaybillIndex index) {
        return WaybillStatus.canQuote(this.getStatus())
                && index.canQuote()
                && this.canQuote();
    }

    protected boolean canBill(WaybillIndex index) {
        return WaybillStatus.canBill(this.getStatus())
                && index.canBill()
                && this.canBill();
    }

    public void buildQuotation(WaybillIndex index) {
        this.quotation().map(quotation -> {
            this.setQuotationId(quotation.getQuotationId());
            this.setQuotationNo(quotation.getQuotationNo());
            this.setQuotationStatus(quotation.getStatus());
            return quotation;
        });

        if (Quotation.endQuote(this, index)) {
            this.closeQuote();
        }

        this.setCallQuote(this.canQuote(index));
    }


    public void buildBill(WaybillIndex index) {
        this.bill().map(bill -> {
            this.setBillId(bill.getBillId());
            this.setBillNo(bill.getBillNo());
            this.setBillName(bill.getName());
            this.setBillStatus(bill.getStatus());
            this.setBillAt(bill.getCreateAt());
            return bill;
        });
        this.setCallBill(this.canBill(index));
    }

//    private BigDecimal getSettledFee(WaybillIndex index) {
////        if (null == this.balances) {
////            return BigDecimal.ZERO;
////        }
////        var prepayFee = this.balances.getSettledFee(PREPAY, index.getPrepayFee());
////        var arrivePayFee = this.balances.getSettledFee(ARRIVE_PAY, index.getArrivePayFee());
////        var collectionFee = this.balances.getSettledFee(COLLECTION, index.getCollectionFee());
////        var receiptFee = this.balances.getSettledFee(RECEIPT, index.getReceiptFee());
////        return prepayFee.add(collectionFee).add(arrivePayFee).add(receiptFee);
//        return null;
//    }

    public void buildBalance(WaybillIndex index) {
        this.setBalances(Balances.split(index.getBalances(), this.getCharacter()));
//
//        // 生成是否有费用标记
//        this.setHasPrepayFee(this.hasFee(PREPAY, index.getPrepayFee()));
//        this.setHasArrivePayFee(this.hasFee(ARRIVE_PAY, index.getArrivePayFee()));
//        this.setHasCollectionFee(this.hasFee(COLLECTION, index.getCollectionFee()));
//        this.setHasReceiptFee(this.hasFee(Balances.RECEIPT, index.getReceiptFee()));
//
//        // 只判断是否收付款，不判断金额
//        var hasBalanceFee = Optional.ofNullable(this.getBalances())
//                .map(bas -> bas.has(Balances.OVERALL, true))
//                .orElse(null);
//        this.setHasBalanceFee(hasBalanceFee);
//
//        this.settledFee = this.getSettledFee(index);
//        if (null != index.getTotalFee()) {
//            this.unsettledFee = index.getTotalFee().subtract(this.settledFee);
//        }
    }

//    public void addReconcile(Reconcile reconcile) {
//        if (null != reconcile) {
////            this.reconcileStatus = reconcile.getStatus();
//        }
//    }
}